﻿using System;
using OpenTK.Math;


namespace Rekx.Graphics
{
    /// <summary>
    /// Container for basic drawable stuff
    /// </summary>
    public class DrawableComponent : IDisposable
    {
        internal Geometry Geometry;
        private Effect effect;
        internal bool hasEffect = false;

        internal bool hasTexture = false;
        private Texture texture;


        /// <summary>
        /// Create a basic drawable component
        /// </summary>
        /// <param name="vertices">Verticies to create it from</param>
        /// <param name="indices">Indices to create it from</param>
        public DrawableComponent(Vector3[] vertices, int[] indices)
        {
            Vector2[] texCoords = new Vector2[]
            {
                new Vector2(0,0),
                new Vector2(1,0),
                new Vector2(0,1),
                new Vector2(1,1)
            };

            Geometry = new Geometry(vertices, indices, texCoords);
        }

        /// <summary>
        /// Creates a drawable component draw with the desired effect
        /// </summary>
        /// <param name="vertices"></param>
        /// <param name="indices"></param>
        /// <param name="effect"></param>
        public DrawableComponent(Vector3[] vertices, int[] indices, Effect effect)
        {
            Vector2[] texCoords = new Vector2[]
            {
                new Vector2(0,0),
                new Vector2(1,0),
                new Vector2(0,1),
                new Vector2(1,1)
            };

            Geometry = new Geometry(vertices, indices, texCoords);
            this.effect = effect;
            hasEffect = true;
        }

        /// <summary>
        /// Sets the effect
        /// </summary>
        public Effect Effect
        {
            set
            {

                if (hasEffect)
                {
                    effect.Dispose();
                }
                this.effect = value;
                hasEffect = true;
            }
            get
            {
                
                    return effect;
            }
        }

        /// <summary>
        /// Gets or sets the texture of the DrawableComponent
        /// </summary>
        public Texture Texture
        {
            set
            {
                if (hasTexture)
                {
                    texture.Dispose();
                }
                this.texture = value;
                 this.hasTexture = true;
            }
            get
            {
                
                return texture;
            }
            
        }

        
        #region IDisposable Pattern
        // taken from msdn

        private bool disposed = false;

        // Implement IDisposable.
        // Do not make this method virtual.
        // A derived class should not be able to override this method.
        
        /// <summary>
        /// Dispose the resources
        /// </summary>
        public void Dispose()
        {
            Dispose(true);
            // This object will be cleaned up by the Dispose method.
            // Therefore, you should call GC.SupressFinalize to
            // take this object off the finalization queue
            // and prevent finalization code for this object
            // from executing a second time.
            GC.SuppressFinalize(this);
        }

        // Dispose(bool disposing) executes in two distinct scenarios.
        // If disposing equals true, the method has been called directly
        // or indirectly by a user's code. Managed and unmanaged resources
        // can be disposed.
        // If disposing equals false, the method has been called by the
        // runtime from inside the finalizer and you should not reference
        // other objects. Only unmanaged resources can be disposed.
        private void Dispose(bool disposing)
        {
            // Check to see if Dispose has already been called.
            if (!this.disposed)
            {
                // If disposing equals true, dispose all managed
                // and unmanaged resources.
                if (disposing)
                {
                    // Dispose managed resources.
                    Geometry.Dispose();
                    if (hasEffect)
                        effect.Dispose();
                    if (hasTexture)
                        texture.Dispose();

                }

                // Call the appropriate methods to clean up
                // unmanaged resources here.
                // If disposing is false,
                // only the following code is executed.
                

                // Note disposing has been done.
                disposed = true;

            }
        }

        #endregion

    }
}
